import { UserCredit } from '../entities/UserCredit';
import { CreditTransaction, TransactionType } from '../entities/CreditTransaction';
import { AppDataSource } from '../config/database';
import { CreditPackage } from '../entities/CreditPackage';
import { Repository } from 'typeorm';

export interface UserCreditInfo {
  userId: number;
  creditBalance: number;
  expiresAt?: Date;
  daysUntilExpiration?: number;
  isExpired: boolean;
}

export interface AddCreditsParams {
  userId: number;
  credits: number;
  validDays: number;
  description?: string;
  referenceId?: string;
  metadata?: Record<string, any>;
}

export interface UseCreditsParams {
  userId: number;
  credits: number;
  description?: string;
  referenceId?: string;
  metadata?: Record<string, any>;
}

export class CreditService {
  private userCreditRepository: Repository<UserCredit>;
  private creditTransactionRepository: Repository<CreditTransaction>;
  private creditPackageRepository: Repository<CreditPackage>;

  constructor() {
    this.userCreditRepository = AppDataSource.getRepository(UserCredit);
    this.creditTransactionRepository = AppDataSource.getRepository(CreditTransaction);
    this.creditPackageRepository = AppDataSource.getRepository(CreditPackage);
  }

  async getCreditPackages(): Promise<CreditPackage[]> {
    return await this.creditPackageRepository.find();
  }

  // 获取或创建用户积分记录
  async getOrCreateUserCredit(userId: number): Promise<UserCredit> {
    let userCredit = await this.userCreditRepository.findOne({ 
      where: { userId } 
    });

    if (!userCredit) {
      // 创建新的用户积分记录
      userCredit = this.userCreditRepository.create({
        userId,
        creditBalance: 0,
        expiresAt: undefined
      });
      await this.userCreditRepository.save(userCredit);
    }

    return userCredit;
  }

  // 获取用户积分信息
  async getUserCreditInfo(userId: number): Promise<UserCreditInfo> {
    const userCredit = await this.getOrCreateUserCredit(userId);
    
    // 检查是否过期
    const now = new Date();
    const isExpired = userCredit.expiresAt ? now > userCredit.expiresAt : false;
    
    // 如果过期，清零积分
    if (isExpired && userCredit.creditBalance > 0) {
      await this.expireCredits(userId);
      userCredit.creditBalance = 0;
      userCredit.expiresAt = undefined;
    }

    // 计算到期天数
    let daysUntilExpiration: number | undefined;
    if (userCredit.expiresAt && !isExpired) {
      const diffTime = userCredit.expiresAt.getTime() - now.getTime();
      daysUntilExpiration = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
    }

    return {
      userId,
      creditBalance: userCredit.creditBalance,
      expiresAt: userCredit.expiresAt || undefined,
      daysUntilExpiration,
      isExpired
    };
  }

  // 添加积分
  async addCredits(params: AddCreditsParams): Promise<UserCreditInfo> {
    const { userId, credits, validDays, description, referenceId, metadata } = params;
    
    if (credits <= 0) {
      throw new Error('积分数量必须大于0');
    }

    const userCredit = await this.getOrCreateUserCredit(userId);

    // 计算新的过期时间
    const expiresAt = new Date();
    expiresAt.setDate(expiresAt.getDate() + validDays);

    // 更新积分余额和过期时间
    userCredit.creditBalance += credits;
    userCredit.expiresAt = expiresAt;

    await this.userCreditRepository.save(userCredit);

    // 记录交易
    await this.addTransaction({
      userId,
      transactionType: 'purchase',
      creditAmount: credits,
      description: description || `购买了 ${credits} 积分`,
      referenceId,
      metadata
    });

    return this.getUserCreditInfo(userId);
  }

  // 使用积分
  async useCredits(params: UseCreditsParams): Promise<UserCreditInfo> {
    const { userId, credits, description, referenceId, metadata } = params;
    
    if (credits <= 0) {
      throw new Error('积分使用数量必须大于0');
    }

    const userCredit = await this.getOrCreateUserCredit(userId);
    
    // 检查积分是否足够
    if (userCredit.creditBalance < credits) {
      throw new Error(`积分不足，当前余额: ${userCredit.creditBalance}, 需要: ${credits}`);
    }

    // 检查积分是否过期
    const now = new Date();
    if (userCredit.expiresAt && now > userCredit.expiresAt) {
      await this.expireCredits(userId);
      throw new Error('积分已过期，无法使用');
    }

    // 减少积分
    userCredit.creditBalance -= credits;
    await this.userCreditRepository.save(userCredit);

    // 记录交易
    await this.addTransaction({
      userId,
      transactionType: 'usage',
      creditAmount: -credits,
      description: description || `使用了 ${credits} 积分`,
      referenceId,
      metadata
    });

    return this.getUserCreditInfo(userId);
  }

  // 积分过期处理
  async expireCredits(userId: number): Promise<void> {
    const userCredit = await this.getOrCreateUserCredit(userId);

    if (userCredit.creditBalance > 0) {
      // 记录过期交易
      await this.addTransaction({
        userId,
        transactionType: 'expiration',
        creditAmount: -userCredit.creditBalance,
        description: `积分过期，清零 ${userCredit.creditBalance} 积分`
      });

      // 清零积分
      userCredit.creditBalance = 0;
      userCredit.expiresAt = undefined;
      await this.userCreditRepository.save(userCredit);
    }
  }

  // 添加交易记录
  async addTransaction(params: {
    userId: number;
    transactionType: TransactionType;
    creditAmount: number;
    description?: string;
    referenceId?: string;
    metadata?: Record<string, any>;
  }): Promise<CreditTransaction> {
    const transaction = this.creditTransactionRepository.create({
      userId: params.userId,
      transactionType: params.transactionType,
      creditAmount: params.creditAmount,
      description: params.description,
      referenceId: params.referenceId,
      metadata: params.metadata
    });

    return await this.creditTransactionRepository.save(transaction);
  }

  // 获取用户交易历史
  async getUserTransactions(
    userId: number, 
    limit: number = 20, 
    offset: number = 0
  ): Promise<CreditTransaction[]> {
    return await this.creditTransactionRepository.find({
      where: { userId },
      order: { createdAt: 'DESC' },
      take: limit,
      skip: offset
    });
  }

  // 处理支付成功后的积分添加
  async handlePaymentSuccess(
    userId: number,
    packageId: string,
    paymentIntentId: string
  ): Promise<UserCreditInfo> {
    const packages = await this.getCreditPackages();
    const package_ = packages.find(p => p.id === packageId);
    
    if (!package_) {
      throw new Error('积分包不存在');
    }

    return await this.addCredits({
      userId,
      credits: package_.credits,
      validDays: package_.validDays,
      description: `购买 ${package_.name} 积分包`,
      referenceId: paymentIntentId,
      metadata: {
        packageId,
        packageName: package_.name,
        packagePrice: package_.price
      }
    });
  }

  // 检查并清理过期积分（定时任务用）
  async checkAndExpireCredits(): Promise<number> {
    const now = new Date();
    
    // 查找所有过期的积分记录
    const expiredCredits = await this.userCreditRepository
      .createQueryBuilder('userCredit')
      .where('userCredit.expiresAt <= :now', { now })
      .andWhere('userCredit.creditBalance > 0')
      .getMany();

    let expiredCount = 0;
    
    for (const userCredit of expiredCredits) {
      await this.expireCredits(userCredit.userId);
      expiredCount++;
    }

    return expiredCount;
  }
}